package se.webbzon.boltzmann.game.event;

import java.util.ArrayList;
import java.util.Collection;

import se.webbzon.boltzmann.camera.AbstractCamera;
import se.webbzon.boltzmann.camera.Camera;
import se.webbzon.boltzmann.game.object.player.AbstractPlayerCharacter;
import se.webbzon.boltzmann.game.sequence.Sequence;
import se.webbzon.boltzmann.game.sequence.builder.AbstractSequenceBinding;
import se.webbzon.oschi01.worldarea.WorldArea;
import se.webbzon.oschi01.worldcamera.WorldView;
import se.webbzon.oschi01.worldobject.WorldObject;

public class SetCameraEvent extends AbstractGameEvent {
	
	// Whatever all cameras should be set
	private final boolean all;
	
	// The sequence of associated with this event
	private final Sequence sequence;
	
	// The camera associated with this event
	private final WorldObject binding;
	
	/*============================================================
	Constructors
	============================================================*/
	
	public SetCameraEvent(Sequence sequence, WorldObject binding, boolean all) {
		this.sequence = sequence;
		this.binding = binding;
		this.all = all;
	}
	
	/*============================================================
	Public Methods
	============================================================*/

	@Override protected void onBegin(WorldArea world) {
		if (binding instanceof AbstractCamera) {
			Camera newCamera = (Camera) binding;
			Collection<AbstractCamera> allCameras = world.findInstances(AbstractCamera.class);
			if (all) 
				setAll(allCameras,newCamera);
			else
				setSingle(allCameras,newCamera);
		}
		end();
	}

	@Override protected void onEnd() {};
	
	/*============================================================
	Private Methods
	============================================================*/
	
	/** Sets the camera for the player associated with the
	 *  sequence of this event. **/
	private final void setSingle(Collection<AbstractCamera> allCameras, Camera newCamera) {
		WorldObject wo = sequence.getBinding(AbstractSequenceBinding.PLAYER);
		if (wo instanceof AbstractPlayerCharacter) {
			WorldView view = ((AbstractPlayerCharacter) wo).getPlayer().getView();
			for (Camera c : allCameras)
				c.removeView(view);
			newCamera.addView(view);
		}
	}
	
	/** Sets the camera for all the views in the world. **/
	private final void setAll(Collection<AbstractCamera> allCameras, Camera newCamera) {
		Collection<WorldView> views = new ArrayList<WorldView>();
		for (Camera c : allCameras) {
			Collection<WorldView> cameraViews = c.getViews();
			synchronized (cameraViews) {
				views.addAll(cameraViews);
			}
			c.clearViews();
		}
		for (WorldView view : views)
			newCamera.addView(view);
	}

}
